function obj = dataAcquisition(obj)
    import MeasurementComponent.Signal.*
    L = log4m.getLogger();
    nmrg = obj.boss;
    param = obj.dataPackage.parameters;    
    measurement_data.start = datetime('now');

    %%
    transvers_channel = nmrg.ziSlave.LockInChannel(4);
    phase_machine = nmrg.ziMaster;
    phase_node = ziSweepNode.Demod2_PhaseShift;
    phase_range1 = param.quadrantX*180;
    phase_range2 = param.quadrantY*180;
    
    %----------------
    nmrg.by.setDC(param.initialBy0); 
    nmrg.bx.reset().setAC('frequency', param.frequencyTrans, ...
                          'amplitude', param.amplitudeTransX, ...
                          'offset',    param.initialBx0);
    bxSig = Signal('bxAmplitude', transvers_channel, ...
                   'reference',   nmrg.bx);    
    bxSig.subscribe_signal(ziDemodTime.R_avg);
    
    %----------------
    nmrg.bTrans.setupLIAchannel('phase', phase_range1); pause(5.0);
    RawPhaseXData = bxSig.getParameterDependence(phase_machine, ...
                                                 phase_node, ...
                                                 phase_range1, ...
                                                 phase_range1+180.0, ...
                                                 'npoint', param.nPoint, ...
                                                 'averaging_sample', param.nAverage);
    RawPhaseXFitting = swpPhaseFitting(RawPhaseXData);
    
    %----------------
    nmrg.bTrans.setupLIAchannel('phase', RawPhaseXFitting.phase0-2.0); pause(5.0);
    FinePhaseXData = bxSig.getParameterDependence(phase_machine, ...
                                                  phase_node, ...
                                                  RawPhaseXFitting.phase0-2.0, ...
                                                  RawPhaseXFitting.phase0+2.0, ...
                                                  'npoint', 20, ...
                                                  'averaging_sample', 50);
    FinePhaseXFitting = swpPhaseFineFitting(FinePhaseXData);
    nmrg.bx.disable();
    
    %==================================
    nmrg.bx.setDC(param.initialBx0); 
    nmrg.by.reset().setAC('frequency', param.frequencyTrans, ...
                          'amplitude', param.amplitudeTransY, ...
                          'offset',    param.initialBy0,'range',10);
    bySig = Signal('byAmplitude', transvers_channel, ...
                   'reference', nmrg.by);
    bySig.subscribe_signal(ziDemodTime.R_avg);
    
    %----------------
    nmrg.bTrans.setupLIAchannel('phase', phase_range2); pause(5.0);
    RawPhaseYData = bySig.getParameterDependence(phase_machine, ...
                                                 phase_node, ...
                                                 phase_range2, ...
                                                 phase_range2+180.0, ...
                                                 'npoint', param.nPoint, ...
                                                 'averaging_sample', param.nAverage);
    RawPhaseYFitting = swpPhaseFitting(RawPhaseYData); 
    
    %----------------
    nmrg.bTrans.setupLIAchannel('phase', RawPhaseYFitting.phase0-2.0); pause(5.0);
    FinePhaseYData = bySig.getParameterDependence(phase_machine, ...
                                                  phase_node, ...
                                                  RawPhaseYFitting.phase0-2.0, ...
                                                  RawPhaseYFitting.phase0+2.0, ...
                                                  'npoint', 20, ...
                                                  'averaging_sample', 50);
    FinePhaseYFitting = swpPhaseFineFitting(FinePhaseYData);
    nmrg.by.disable();
    
    %==================================
    nmrg.bTrans.setupLIAchannel('phase', FinePhaseYFitting.phase0);
    nmrg.bTransDCx.setupLIAchannel('phase', FinePhaseYFitting.phase0);
    nmrg.bTransDCy.setupLIAchannel('phase', FinePhaseXFitting.phase0);
    L.info('NMRGyroscope::GetWorkingPoint', sprintf('PhaseX = %5.3f, PhaseY = %5.3f', FinePhaseXFitting.phase0, FinePhaseYFitting.phase0));
    
    
    %==================================
    bias_machin_x = nmrg.ziSlave;
    bias_machin_y = nmrg.ziSlave;
    bias_node_x = ziSweepNode.AuxOut1_Offset;
    bias_node_y = ziSweepNode.SigOut_Offset;
    
    %----------------
    nmrg.bx.setDC(param.initialBx0); nmrg.by.setDC(param.initialBy0);
    transSigGroup = SignalGroup('TransSignals');
    transSigGroup.subscribe_signal(nmrg.bTransDCx, ziDemodTime.X_avg, [2, 1, 1]);
    transSigGroup.subscribe_signal(nmrg.bTransDCy, ziDemodTime.X_avg, [2, 1, 2]);
    BiasXData = transSigGroup.getParameterDependence(bias_machin_x, ...
                                                         bias_node_x, ...
                                                         param.initialBx0-0.1, ...
                                                         param.initialBx0+0.1, ...
                                                         'npoint', 10, ...
                                                         'averaging_sample', 1);
    BiasXFitting = swpSlopeFitting(BiasXData);
    nmrg.bx.setDC(BiasXFitting.zeropoint);
    L.info('NMRGyroscope::GetWorkingPoint', sprintf('BiasX = %5.3f', BiasXFitting.zeropoint));
    
    %----------------
    range = [param.initialBy0-0.1, param.initialBy0+0.1];
    nmrg.by.port.setOutputRange( max(abs(range)) ); pause(0.1);
    
    transSigGroup.unsubscribe_signal();
    transSigGroup.subscribe_signal(nmrg.bTransDCy, ziDemodTime.X_avg, [2, 1, 1]);
    transSigGroup.subscribe_signal(nmrg.bTransDCx, ziDemodTime.X_avg, [2, 1, 2]);
    BiasYData = transSigGroup.getParameterDependence(bias_machin_y, ...
                                                         bias_node_y, ...
                                                         param.initialBy0-0.1, ...
                                                         param.initialBy0+0.1, ...
                                                         'npoint', 10, ...
                                                         'averaging_sample', 1);
    BiasYFitting = swpSlopeFitting(BiasYData);
    nmrg.by.setDC(BiasYFitting.zeropoint);
    L.info('NMRGyroscope::GetWorkingPoint', sprintf('BiasY = %5.3f', BiasYFitting.zeropoint));
    
    
    %%
    measurement_data.RawPhaseXData = RawPhaseXData;
    measurement_data.RawPhaseYData = RawPhaseYData;
    measurement_data.FinePhaseXData = FinePhaseXData;
    measurement_data.FinePhaseYData = FinePhaseYData;
    measurement_data.BiasXData = BiasXData;
    measurement_data.BiasYData = BiasYData;
    
    measurement_data.RawPhaseXFitting = RawPhaseXFitting;
    measurement_data.RawPhaseYFitting = RawPhaseYFitting;
    measurement_data.FinePhaseXFitting = FinePhaseXFitting;
    measurement_data.FinePhaseYFitting = FinePhaseYFitting; 
    measurement_data.BiasXFitting = BiasXFitting;
    measurement_data.BiasYFitting = BiasYFitting;

    measurement_data.finish = datetime('now');
    obj.dataPackage.measurement_data = measurement_data;
end


function fitting = swpPhaseFitting(swprResult)
    data = swprResult.getNodeData(1); 
    [xData, yData] = prepareCurveData(data.x, data.y);

    amp = max(data.y); [~, idx] = min(data.y); phi0 = data.x(idx);
    % Set up fittype and options.
    ft = fittype( 'abs(A*sin(x/180*pi-phi)+B)', 'independent', 'x', 'dependent', 'y' );
    opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
    opts.Display = 'Off';
    opts.Lower =      [amp*0.5 0 0];
    opts.StartPoint = [amp     0 phi0/180*pi];
    opts.Upper =      [amp*1.5 0 2*pi];

    % Fit model to data.
    [fitresult, gof] = fit( xData, yData, ft, opts );
    phase0 = fitresult.phi/pi*180;
    
    fitting.phase0 = phase0;
    fitting.result = fitresult;
    fitting.gof = gof;
end

function fitting = swpPhaseFineFitting(swprResult)
    data = swprResult.getNodeData(1);
    [xData, yData] = prepareCurveData(data.x, data.y.^2);
    
    ft = fittype( 'poly2' );
    excludedPoints = excludedata( xData, yData, 'Indices', 1);
    opts = fitoptions( );
    opts.Exclude = excludedPoints;
    [fitresult, gof] = fit( xData, yData, ft, opts );
    phase0 = -fitresult.p2/2.0/fitresult.p1;
    
    minVal = fitresult.p3 - fitresult.p2^2/4.0/fitresult.p1;
    if minVal >= 0.0
        residual = sqrt(minVal);
        model = 'poly2';
    else
        [xData, yData] = prepareCurveData(data.x, data.y);
        ft1 = fittype( 'a*abs(x-x0)+b', 'independent', 'x', 'dependent', 'y' );
        opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
        opts.Display = 'Off';
        opts.StartPoint = [sqrt(fitresult.p1), 0.0, phase0];
        opts.Lower = [0 0 0];
        excludedPoints = excludedata( xData, yData, 'Indices', 1);
        opts.Exclude = excludedPoints;
        [fitresult, gof] = fit( xData, yData, ft1, opts );
        
        phase0 = fitresult.x0; residual = fitresult.b;
        model = 'abs';
    end
    fitting.phase0 = phase0;
    fitting.residual = residual;
    fitting.model = model;
    fitting.result = fitresult;
    fitting.gof = gof;
end

function fitting = swpSlopeFitting(swprResult)
    data = swprResult.getNodeData(1);
    [xData, yData] = prepareCurveData( data.x, data.y );

    ft = fittype( 'poly1' );
    opts = fitoptions( 'Method', 'LinearLeastSquares' );

    [result, gof] = fit( xData, yData, ft, opts );
    slope = result.p1;
    zeropoint = -result.p2./result.p1;
    
    fitting.slope = slope;
    fitting.zeropoint =zeropoint;
    fitting.result =result;
    fitting.gof = gof;
end